/**
 * Excel文件导出模块
 * 专门用于处理Excel文件流下载操作
 */

import service from '@/utils/request'
import { ElMessage } from 'element-plus'
import { getMemberId, getWarehouseId, getWarehouseName } from '@/utils/globalConfig'

/**
 * 处理HTTP错误状态码
 * @param {Object} error - axios错误对象
 * @returns {String} 友好的错误信息
 */
function handleHttpError(error) {
  if (error.response) {
    // 服务器返回了错误状态码
    const status = error.response.status
    switch (status) {
      case 400:
        return '请求参数错误，请检查导出条件'
      case 401:
        return '登录状态已过期，请重新登录'
      case 402:
        return '禁止使用默认密码登录，请修改密码'
      case 403:
        return '密码已变更，请重新登录'
      case 404:
        return '导出接口不存在，请联系管理员'
      case 500:
        return '服务器内部错误，请稍后重试'
      case 502:
        return '网关错误，请稍后重试'
      case 503:
        return '服务暂时不可用，请稍后重试'
      case 504:
        return '网关超时，请稍后重试'
      default:
        return `服务器响应错误(${status})`
    }
  } else if (error.request) {
    // 请求已发送但未收到响应
    return '服务器无响应，请检查网络连接'
  } else {
    // 请求配置出错
    return '请求配置错误，无法发送请求'
  }
}

/**
 * Excel文件导出函数
 * @param {String} url - 接口地址
 * @param {Object} params - 请求参数(JSON格式)
 * @param {String} fileName - 可选，自定义下载文件名，不传则使用响应头中的文件名
 * @returns {Promise}
 */
export function exportExcel(url, params = {}, fileName = '') {
  return new Promise((resolve, reject) => {
    // 使用封装的service实例代替直接axios调用
    service({
      method: 'post',
      url,
      data: params,
      responseType: 'blob',
      headers: {
        'Content-Type': 'application/json'
      }
    })
      .then(response => {
        // 检查是否返回了错误信息
        if (response.data.type === 'application/json') {
          // 将Blob转换为文本，然后解析JSON
          const reader = new FileReader()
          reader.onload = () => {
            try {
              const errorData = JSON.parse(reader.result)
              // 显示错误信息
              ElMessage({
                message: errorData.message || '导出失败',
                type: 'error',
                duration: 3 * 1000
              })
              reject(errorData)
            } catch (e) {
              // 如果不是JSON，当作正常文件处理
              try {
                handleExcelDownload(response, fileName)
                resolve(response)
              } catch (err) {
                console.error('文件处理失败:', err)
                ElMessage({
                  message: '文件处理失败，请重试',
                  type: 'error',
                  duration: 3 * 1000
                })
                reject(err)
              }
            }
          }
          reader.onerror = (event) => {
            console.error('文件读取失败:', event)
            ElMessage({
              message: '文件读取失败，请重试',
              type: 'error',
              duration: 3 * 1000
            })
            reject(new Error('文件读取失败'))
          }
          reader.readAsText(response.data)
        } else {
          // 正常的文件流响应，处理下载
          try {
            handleExcelDownload(response, fileName)
            resolve(response)
          } catch (err) {
            console.error('文件处理失败:', err)
            ElMessage({
              message: '文件处理失败，请重试',
              type: 'error',
              duration: 3 * 1000
            })
            reject(err)
          }
        }
      })
      .catch(error => {
        console.error('Excel导出请求失败:', error)
        
        // 获取详细的HTTP错误信息
        const errorMessage = handleHttpError(error)
        
        ElMessage({
          message: `Excel导出失败: ${errorMessage}`,
          type: 'error',
          duration: 5 * 1000
        })
        
        // 为错误对象添加友好的错误信息
        if (error.response) {
          error.friendlyMessage = errorMessage
        }
        
        reject(error)
      })
  })
}

/**
 * Excel文件导出函数 - GET方法版本
 * @param {String} url - 接口地址
 * @param {Object} params - 请求参数
 * @param {String} fileName - 可选，自定义下载文件名
 * @returns {Promise}
 */
export function exportExcelByGet(url, params = {}, fileName = '') {
  return new Promise((resolve, reject) => {
    // 使用封装的service实例代替直接axios调用
    service({
      method: 'get',
      url,
      params: params,
      responseType: 'blob'
    })
      .then(response => {
        // 检查是否返回了错误信息
        if (response.data.type === 'application/json') {
          // 将Blob转换为文本，然后解析JSON
          const reader = new FileReader()
          reader.onload = () => {
            try {
              const errorData = JSON.parse(reader.result)
              // 显示错误信息
              ElMessage({
                message: errorData.message || '导出失败',
                type: 'error',
                duration: 3 * 1000
              })
              reject(errorData)
            } catch (e) {
              // 如果不是JSON，当作正常文件处理
              try {
                handleExcelDownload(response, fileName)
                resolve(response)
              } catch (err) {
                console.error('文件处理失败:', err)
                ElMessage({
                  message: '文件处理失败，请重试',
                  type: 'error',
                  duration: 3 * 1000
                })
                reject(err)
              }
            }
          }
          reader.onerror = (event) => {
            console.error('文件读取失败:', event)
            ElMessage({
              message: '文件读取失败，请重试',
              type: 'error',
              duration: 3 * 1000
            })
            reject(new Error('文件读取失败'))
          }
          reader.readAsText(response.data)
        } else {
          // 正常的文件流响应，处理下载
          try {
            handleExcelDownload(response, fileName)
            resolve(response)
          } catch (err) {
            console.error('文件处理失败:', err)
            ElMessage({
              message: '文件处理失败，请重试',
              type: 'error',
              duration: 3 * 1000
            })
            reject(err)
          }
        }
      })
      .catch(error => {
        console.error('Excel导出请求失败:', error)
        
        // 获取详细的HTTP错误信息
        const errorMessage = handleHttpError(error)
        
        ElMessage({
          message: `Excel导出失败: ${errorMessage}`,
          type: 'error',
          duration: 5 * 1000
        })
        
        // 为错误对象添加友好的错误信息
        if (error.response) {
          error.friendlyMessage = errorMessage
        }
        
        reject(error)
      })
  })
}

/**
 * 处理Excel文件下载
 * @param {Object} response - 响应对象
 * @param {String} customFileName - 自定义文件名
 */
function handleExcelDownload(response, customFileName) {
  try {
    // 从响应头获取文件名
    let fileName = customFileName
    if (!fileName) {
      // 从响应头获取文件名
      const contentDisposition = response.headers['content-disposition']
      if (contentDisposition) {
        // 使用正则表达式从Content-Disposition中提取文件名
        const filenameRegex = /filename[^;=\n]*=((['"]).*?\2|[^;\n]*)/
        const matches = filenameRegex.exec(contentDisposition)
        if (matches != null && matches[1]) {
          // 处理引号和URL编码
          fileName = matches[1].replace(/['"]/g, '')
          // 尝试解码文件名，如果是URL编码的
          try {
            fileName = decodeURIComponent(fileName)
          } catch (e) {
            // 如果解码失败，使用原始文件名
            console.warn('文件名解码失败', e)
          }
        }
      }
      
      // 如果无法从响应头获取文件名，生成默认Excel文件名
      if (!fileName) {
        const timestamp = new Date().getTime()
        // 检查内容类型以确定正确的扩展名
        const contentType = response.headers['content-type']
        let extension = '.xlsx' // 默认为.xlsx
        
        if (contentType) {
          if (contentType === 'application/vnd.ms-excel') {
            extension = '.xls'
          } else if (contentType === 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet') {
            extension = '.xlsx'
          }
        }
        
        fileName = `export_${timestamp}${extension}`
      }
    }

    // 创建Blob URL
    const blob = new Blob([response.data], { 
      type: 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet'
    })
    const url = window.URL.createObjectURL(blob)
    
    // 创建一个链接并模拟点击下载
    const link = document.createElement('a')
    link.href = url
    link.setAttribute('download', fileName)
    document.body.appendChild(link)
    link.click()
    
    // 清理DOM和释放Blob URL
    document.body.removeChild(link)
    window.URL.revokeObjectURL(url)
  } catch (error) {
    console.error('Excel文件下载失败:', error)
    ElMessage({
      message: '文件下载失败，请重试',
      type: 'error',
      duration: 3 * 1000
    })
    throw error // 重新抛出错误，让上层函数可以处理
  }
}

/**
 * 导出多个Excel文件的批量导出函数
 * @param {Array} exportTasks - 导出任务数组，每个元素包含url和params
 * @param {Boolean} sequential - 是否按顺序执行导出，默认为false（并行导出）
 * @returns {Promise}
 */
export function batchExportExcel(exportTasks, sequential = false) {
  if (!Array.isArray(exportTasks) || exportTasks.length === 0) {
    return Promise.reject(new Error('导出任务不能为空'))
  }

  // 转换每个任务为Promise
  const tasks = exportTasks.map(task => {
    const { url, params, fileName } = task
    return () => exportExcel(url, params, fileName)
  })

  // 根据sequential参数决定是并行还是顺序执行
  if (sequential) {
    // 顺序执行
    return tasks.reduce((promise, task) => {
      return promise.then(results => {
        return task().then(result => [...results, result])
          .catch(error => {
            console.error('批量导出任务执行失败:', error)
            // 即使某个任务失败，仍然返回已完成的结果
            return [...results, { error, success: false }]
          })
      })
    }, Promise.resolve([]))
  } else {
    // 并行执行 - 使用Promise.allSettled代替Promise.all以处理部分失败情况
    return Promise.allSettled(tasks.map(task => task()))
      .then(results => {
        // 处理结果，分离成功和失败的任务
        const processedResults = results.map(result => {
          if (result.status === 'fulfilled') {
            return { data: result.value, success: true }
          } else {
            console.error('批量导出任务失败:', result.reason)
            return { error: result.reason, success: false }
          }
        })
        
        // 检查是否所有任务都失败了
        const allFailed = processedResults.every(result => !result.success)
        if (allFailed) {
          ElMessage({
            message: '所有导出任务均失败',
            type: 'error',
            duration: 3 * 1000
          })
        } else if (processedResults.some(result => !result.success)) {
          ElMessage({
            message: '部分导出任务失败',
            type: 'warning',
            duration: 3 * 1000
          })
        }
        
        return processedResults
      })
  }
} 